package com.jeesite.modules.dataScreen.web.vo;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.jeesite.modules.dataScreen.enums.IndustryIndexColorEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.val;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Data
@ApiModel("指标对象")
@AllArgsConstructor
@NoArgsConstructor
public class IndustryIndexVo {

    static Map<String, List<Range>> cache = new ConcurrentHashMap<>();

    public static IndustryIndexVo NULL = new IndustryIndexVo();

    public IndustryIndexVo(String indicatorName, String indicatorValue, String unit) {
        this.indicatorName = indicatorName;
        this.indicatorValue = indicatorValue;
        this.unit = unit;
    }

    @ApiModelProperty("板块")
    private String plate;

    @ApiModelProperty("跑道")
    private String runway;

    @ApiModelProperty("子跑道")
    private String subRunway;

    @ApiModelProperty("指标名称")
    private String indicatorName;

    @ApiModelProperty("指标值")
    private String indicatorValue;

    @ApiModelProperty("计量单位")
    private String unit;

    @ApiModelProperty("是否预警：0正常，1预警")
    private Integer valueresult;

    @ApiModelProperty("预警阈值")
    private String thresholdstr;

    @ApiModelProperty("预警url")
    private String url;
    //idxevaldimensiondata
    //idxbusidimensiondata
    //idxtimedimensiondata

    @ApiModelProperty("预警颜色")
    private String color;

    @ApiModelProperty("预警提示")
    private String warningTitle;

    public static BigDecimal addAll(IndustryIndexVo... vos) {
        if (vos.length == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal result = new BigDecimal(0);
        for (IndustryIndexVo vo : vos) {
            result = result.add(val(vo));
        }
        return result;
    }

    public static BigDecimal addAll(Map<String, IndustryIndexVo> dataMap, Collection<String> keys) {
        if (CollUtil.isEmpty(keys) || CollUtil.isEmpty(dataMap)) {
            return BigDecimal.ZERO;
        }
        BigDecimal result = new BigDecimal(0);
        for (String key : keys) {
            result = result.add(val(dataMap.get(key)));
        }
        return result;
    }

    public static BigDecimal addAll(List<IndustryIndexVo> vos) {
        if (vos.size() == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal result = new BigDecimal(0);
        for (IndustryIndexVo vo : vos) {
            result = result.add(val(vo));
        }
        return result;
    }

    public static BigDecimal val(IndustryIndexVo vo) {
        if (Objects.nonNull(vo) && StrUtil.isNotBlank(vo.getIndicatorValue())) {
            return new BigDecimal(vo.getIndicatorValue());
        }
        return BigDecimal.ZERO;
    }

    /**
     * 除法计算
     * 结果值[0~100]
     *
     * @param v1    被除
     * @param v2
     * @param scale
     * @param mode
     * @return
     */
    public static BigDecimal divide(IndustryIndexVo v1, IndustryIndexVo v2, int scale, RoundingMode mode) {
        BigDecimal var1 = val(v1);
        BigDecimal var2 = val(v2);

        if (var2.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        return var1.multiply(BigDecimal.valueOf(100)).divide(var2, scale, mode);
    }


    /**
     * 计算一个属性在一个饼图中的多个属性中所占的比例
     *
     * @param v1
     * @param scale
     * @param mode
     * @param vos
     * @return
     */
    public static BigDecimal divide(IndustryIndexVo v1, int scale, RoundingMode mode, IndustryIndexVo... vos) {
        BigDecimal var1 = val(v1);
        BigDecimal sum = BigDecimal.ZERO;
        for (IndustryIndexVo vo : vos) {
            BigDecimal vovo = val(vo);
            sum = sum.add(vovo);
        }

        if (sum.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }

        return var1.multiply(BigDecimal.valueOf(100)).divide(sum, scale, mode);
    }

    public static String[] titleAndColor(IndustryIndexVo indexVo) {
        if (indexVo == null || StrUtil.isBlank(indexVo.getIndicatorValue())) {
            return null;
        }
        List<Range> ranges = IndustryIndexColorEnum.getRange(indexVo.getIndicatorName());
        if (CollUtil.isNotEmpty(ranges)) {
            BigDecimal value = val(indexVo);
            for (Range rangeObj : ranges) {
                if (rangeObj.inRange(value)) {
                    return new String[]{rangeObj.getWarningTitle(), rangeObj.getColor()};
                }
            }
        }
        return null;
    }

    public static String color(IndustryIndexVo indexVo) {
        String[] strings = titleAndColor(indexVo);
        if (Objects.nonNull(strings)) {
            return strings[1];
        }
        return null;
    }

    @Data
    public static class Range {

        public static final String MAX_VAL = "999999999";
        public static final String MIN_VAL = "0.001";
        static final List<String> IGNORE_VALUE = CollUtil.toList("0", MIN_VAL, MAX_VAL);

        Range(BigDecimal min, BigDecimal max, String color, String warningTitle) {
            this.min = min;
            this.max = max;
            this.color = color;
            this.warningTitle = warningTitle;
        }

        public static Range of(String min, String max, String color) {
            StringBuilder sb = new StringBuilder();
            if (!IGNORE_VALUE.contains(min)) {
                sb.append("大于等于").append(min);
            }
            if (!IGNORE_VALUE.contains(max)) {
                sb.append("小于").append(max);
            }
            return new Range(new BigDecimal(min), new BigDecimal(max), color, sb.toString());
        }

        private BigDecimal min;
        private BigDecimal max;
        private String color;
        private String warningTitle;

        public boolean inRange(BigDecimal value) {
            return value.compareTo(min) >= 0 && value.compareTo(max) < 0;
        }
    }


    public static Consumer<IndustryIndexVo> consumerColor() {
        return vo -> vo.setColor(IndustryIndexVo.color(vo));
    }
}
